package uk.co.hs.web.security.service;

import java.util.ArrayList;
import java.util.Collection;

import javax.annotation.Resource;

import org.joda.time.DateTime;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import uk.co.hs.dao.web.admin.WebUserDao;
import uk.co.hs.domain.web.WebRole;
import uk.co.hs.domain.web.WebUser;

/**
 * UtilisoftUserSecurityServiceNOSSO.
 */
@Service("hs_security.userService.nosso")
@Transactional(value="hs_transactionManager")
public class UtilisoftUserSecurityServiceNOSSO implements UserDetailsService
{
  @Resource
  private WebUserDao mUserDao;

  private static int mValidPasswordPeriodDays;

  public static void setValidPasswordPeriodDays(int aValidPasswordPeriodDays)
	{
		mValidPasswordPeriodDays = aValidPasswordPeriodDays;
	}

  /**
   * @see org.springframework.security.core.userdetails.UserDetailsService
   * #loadUserByUsername(java.lang.String)
   * {@inheritDoc}
   */
  public UserDetails loadUserByUsername(String aUsername) throws UsernameNotFoundException, DataAccessException
  {
    WebUser user = mUserDao.getWebUser(aUsername);
    if (user == null)
    {
      throw new UsernameNotFoundException("No Username found.");
    }
    return buildUserFromUserEntity(user);
  }

  public User buildUserFromUserEntity(WebUser aUserEntity)
  {
    String username = aUserEntity.getUsername();
    String password = aUserEntity.getPassword();
    boolean enabled = aUserEntity.getActive();
    boolean accountNonExpired = aUserEntity.getActive();

    boolean credentialsNonExpired;
    if (username.equals(WebUser.UTILISOFT_USER))
    {
      credentialsNonExpired = true;
    }
    else
    {
      credentialsNonExpired = getCredentialsNonExpired(aUserEntity.getNewPasswordRequired(), aUserEntity.getLastPasswordChanged());
    }

    boolean accountNonLocked = !aUserEntity.getLocked();

    Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

    // Role
    WebRole role = aUserEntity.getRole();
    if (role != null)
    {
    	authorities.add(new SimpleGrantedAuthority(role.getName()));
    }

    return new User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
  }

  public User buildEmptyUser(String aUsername)
  {
    return new User(aUsername, "none", true, true, true, true, new ArrayList<GrantedAuthority>());
  }

  private boolean getCredentialsNonExpired(Boolean aNewPasswordRequired, DateTime aLastPasswordChangeDate)
  {
    if (aNewPasswordRequired)
    {
      return false;
    }
  	if (aLastPasswordChangeDate == null)
  	{
  		return false;
  	}
  	DateTime currentDate = new DateTime().toDateMidnight().toDateTime();
  	DateTime expiryDate = aLastPasswordChangeDate.plusDays(mValidPasswordPeriodDays);
  	if (currentDate.isAfter(expiryDate))
  	{
  		return false;
  	}
  	return true;
  }
}
